#include "yuvplayer.h"
#include <iostream>

using namespace std;

#define END(condition,func)  if(condition) { \
     qDebug() << #func << " fail"; \
      return; \
}


const static std::map<AVPixelFormat,SDL_PixelFormatEnum> mapFmt = {
    {AV_PIX_FMT_YUV420P,SDL_PIXELFORMAT_IYUV}
};


YUVPlayer::YUVPlayer(YUVSpec &yuvSpec, QWidget *parent):QWidget(parent)
{
    this->yuvSpec = yuvSpec;

    window = SDL_CreateWindowFrom((void *)this->winId());

    END(!window,SDL_CreateWindowFrom);

    render = SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC);


    if(render == nullptr) {

        render = SDL_CreateRenderer(window,-1,SDL_RENDERER_SOFTWARE);
    }

    END(!render,SDL_CreateRenderer);



    texture = SDL_CreateTexture(render,mapFmt.find(yuvSpec.pixelFmt)->second,SDL_TEXTUREACCESS_STREAMING,this->yuvSpec.width,this->yuvSpec.height);

    END(!texture,SDL_CreateTexture);

    SDL_SetRenderDrawColor(render,0,0,0,255);

    SDL_RenderClear(render);

    this->file = new QFile(yuvSpec.yuvPath);

    if(!this->file->open(QFile::ReadOnly)) {

        qDebug() << yuvSpec.yuvPath << " open fail";
        return;
    }

    imageBufferSize = av_image_get_buffer_size(yuvSpec.pixelFmt,yuvSpec.width,yuvSpec.height,1);

    imageBuffer = new char[imageBufferSize];
}

YUVPlayer::~YUVPlayer()
{

    if(timer > 0) {

        killTimer(timer);
    }

    SDL_DestroyRenderer(render);
    SDL_DestroyTexture(texture);
    SDL_DestroyWindow(window);
    if(file != nullptr) {

        file->close();
    }

    if(imageBuffer != nullptr) {

        delete [] imageBuffer;
    }

}

void YUVPlayer::start()
{

   timer = startTimer(1000/yuvSpec.framerate);

   state = YUVPlayer::Playing;
}

void YUVPlayer::stop()
{
    if(timer) {

        killTimer(timer);
    }
    state = YUVPlayer::Stop;
}

void YUVPlayer::pause()
{

    if(timer) {

        killTimer(timer);
    }
    state = YUVPlayer::Pause;
}

bool YUVPlayer::isPlay()
{

    return state == YUVPlayer::Playing;
}

void YUVPlayer::timerEvent(QTimerEvent *event)
{

   int readLen = file->read(imageBuffer,imageBufferSize);

   if(readLen <= 0) {

       killTimer(timer);
       timer = 0;
       state = YUVPlayer::Stop;
   }else{

       state = YUVPlayer::Playing;
       SDL_UpdateTexture(texture,nullptr,imageBuffer,yuvSpec.width);
       SDL_RenderCopy(render,texture,nullptr,nullptr);
       SDL_RenderPresent(render);
   }
}
